#include "event.h"
#include "radar_protocol.h"
#include "config.h"
#include "platform.h"
#include "common.h"
#include <curl/curl.h>
#include "../cJSON/cJSON.h"
#include "snapshot.h"
#include "log.h"
#include <time.h>
#include "video_protocol.h"
#include "dhsdk.h"

/* —— 阈值配置 —— */
#define PARKING_TIME_THRESHOLD_MS       10000LL  // 停车检测持续时间
#define COLLISION_TIME_THRESHOLD_MS     1000LL   // 碰撞检测最大时间间隔（毫秒）
#define COLLISION_DURATION_THRESHOLD_MS 5000LL   // 碰撞检测持续时间（毫秒）
#define COLLISION_DISTY_THRESHOLD       100      // 碰撞检测 Y 轴距离阈值（米）
#define CONGESTION_COUNT_THRESHOLD      5        // 拥堵检测最少车辆数
#define CONGESTION_TIME_WINDOW_MS       1000LL   // 拥堵检测时间窗口（毫秒）

event_manager_t g_event_manager = {0};
extern video_manager_t g_video_manager;

static CURL *curl = NULL;
static char *response = NULL;

// 返回当前分钟数：自 Epoch 起的分钟数
static int current_minute(void)
{
    time_t now = time(NULL);
    return (int)(now / 60);
}

// 计算本次事件对应的“槽”起始分钟
static int current_slot_start(void)
{
    int m = current_minute();
    return m - (m % INTERVAL_MIN);
}

// 处理一个变道事件：position 米
void process_lane_change(int position_meter, int8_t dev_type)
{
    // 1) 确定落在哪段
    int idx = position_meter * SEGMENT_COUNT / SEGMENT_LENGTH;
    if (idx < 0 || idx >= SEGMENT_COUNT) {
        return;  // 超出范围，直接返回
    }

    Queue_t *q = dev_type == RADAR_INCOMING ? g_event_manager.incoming_change_lane_static_queue[idx] : g_event_manager.outgoing_change_lane_static_queue[idx];
    int slot = current_slot_start();

    // 2) 查看队尾是否已有同槽元素
    change_lane_statistic_t *tail = queue_get_node(q, from_tail, 0);
    if (tail && tail->time == slot) {
        // 同一个槽内，直接累加
        tail->count++;
    }
    else {
        // 新槽：构造并入队（满时自动踢老）
        change_lane_statistic_t s = {.time = slot, .count = 1};
        queue_enqueue(q, &s);
    }
}

static int get_recent_lane_change_count_by_distance(int distance, int dev_type)
{
    // 先把 distance → cell 索引
    // 整段 [0 .. SEGMENT_LENGTH) 被均匀划分为 OBSTACLE_SEGMENT 段
    int idx = distance * SEGMENT_COUNT / SEGMENT_LENGTH;
    if (idx < 0 || idx >= SEGMENT_COUNT) {
        return 0;  // 超出范围，直接返回
    }

    // 拿到对应的滑动队列
    Queue_t *q = (dev_type == RADAR_INCOMING) ? g_event_manager.incoming_change_lane_static_queue[idx] : g_event_manager.outgoing_change_lane_static_queue[idx];

    // 队尾元素就是最近一个 2 分钟槽的数据
    int count = 0;
    change_lane_statistic_t *tail = (change_lane_statistic_t *)queue_get_node(q, from_tail, 0);
    if (tail) {
        count = tail->count;
    }
    tail = (change_lane_statistic_t *)queue_get_node(q, from_tail, 1);
    if (tail) {
        count += tail->count;
    }
    return count;
}

/* 回调函数，用来把服务器返回的数据累积到一个字符串里 */
static size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata)
{
    size_t real_size = size * nmemb;
    /* userdata 是我们传进来的 char**，在这里追加数据 */
    char **response_ptr = (char **)userdata;

    /* 扩展缓冲区 */
    *response_ptr = realloc(*response_ptr, strlen(*response_ptr) + real_size + 1);
    if (*response_ptr == NULL) {
        fprintf(stderr, "realloc() failed\n");
        return 0;
    }

    /* 拼接新数据并保证以 '\0' 结尾 */
    strncat(*response_ptr, (char *)ptr, real_size);
    return real_size;
}

void report_lane_change(obj_static_t *obj, int8_t lane)
{
    radar_packet_84_t packet_84 = {0};
    if (lane == g_config.lane_num - 1) {
        if (obj->dev_type == RADAR_INCOMING && obj->dist_y < g_config.in_radar_max_distance && video_detect_emergency_lane() == false) {
            return;
        }
        packet_84.header.event_type = 0x11;  // 占用应急车道事件
    }
    else {
        packet_84.header.event_type = 0x13;  // 车道变更事件
    }
    packet_84.body.va.obj_id = obj->id;
    packet_84.body.va.obj_lane = lane;
    packet_84.body.va.obj_type = obj->obj_type;
    packet_84.body.va.obj_length = 0;
    packet_84.body.va.obj_dist_y_low = obj->dist_y;
    packet_84.body.va.obj_dist_x_low = obj->dist_x;
    packet_84.body.va.obj_speed = obj->current_speed;
    packet_84.body.va.reserve2[0] = obj->report_lane;
    packet_84.body.va.reserve2[1] = lane;

    if (update_event_queue_blg(obj->id, packet_84.header.event_type, obj->dev_type) == false) {
        return;  // 事件已经存在，直接返回
    }

    uint8_t time_stamp[8] = {0};
    send_event_to_platform(&packet_84, time_stamp, obj->dev_type);
}

void report_acceleration(obj_static_t *obj)
{
    radar_packet_84_t packet_84 = {0};
    packet_84.header.event_type = 0x9;  // 加速事件
    packet_84.body.va.obj_id = obj->id;
    packet_84.body.va.obj_lane = obj->report_lane;
    packet_84.body.va.obj_type = obj->obj_type;
    packet_84.body.va.obj_length = 0;
    packet_84.body.va.obj_dist_y_low = obj->dist_y;
    packet_84.body.va.obj_dist_x_low = obj->dist_x;
    packet_84.body.va.obj_speed = obj->current_speed;
    memcpy(packet_84.body.va.reserve2, &obj->acceleration, sizeof(obj->acceleration));
    uint8_t time_stamp[8] = {0};
    send_event_to_platform(&packet_84, time_stamp, obj->dev_type);
}

static void update_lane(obj_static_t *obj, int8_t lane)
{
    int64_t current_time = get_current_time_in_milliseconds();
    int change_timeout = 0;

    if (obj != NULL) {
        if (obj->report_lane != lane) {
            // if (obj->dist_y < 100 ||
            //     (obj->dev_type == RADAR_OUTGOING && obj->dist_y > g_config.outgoing_obstacle_range[1]) ||
            //     (obj->dev_type == RADAR_INCOMING && obj->dist_y > g_config.incoming_obstacle_range[1])) {
            if (obj->dist_y < 200) {
                obj->report_lane = lane;
                return;
            }
            if (obj->dist_y > 2000) {
                change_timeout = g_config.change_lane_timeout * 1000;
            }
            else {
                change_timeout = g_config.change_lane_timeout * 1000 / 2;
            }

            if (obj->current_lane == lane) {
                if ((current_time - obj->change_time) >= change_timeout) {
                    // report_lane_change(obj, lane);

                    // char time_buf[64] = {0};
                    // printf("%s: %s方向发生了车道变更事件, id: 0x%04X, 原道路号: %d, 新道路号: %d, 发生位置: %d\n",
                    //        get_current_time_string(time_buf, sizeof(time_buf)),
                    //        (obj->dev_type == RADAR_INCOMING) ? ">>>>>>>>>来向" : "<<<<<<<<<去向",
                    //        obj->id, obj->report_lane, lane, obj->dist_y);

                    obj->report_lane = lane;
                    return;
                }
            }
            else {
                obj->current_lane = lane;
                obj->change_time = current_time;
            }
        }
    }
}

#define ACCEL_THRESHOLD_G 50  // 加速度阈值，单位为 0.1m/s^2

static void update_acceleration(obj_static_t *obj, int16_t speed_y)
{
    int64_t current_time = get_current_time_in_milliseconds();
    if (current_time - obj->last_speed_time > 1000) {
        float a = (speed_y - obj->last_speed) * 1000.0f / (current_time - obj->last_speed_time);
        obj->acceleration = (int)(a + 0.5f);
        obj->last_speed_time = current_time;
        obj->last_speed = speed_y;
        if (abs(obj->acceleration) > ACCEL_THRESHOLD_G) {
            char time_buf[64] = {0};
            printf("%s: %s方向发生了加速事件, id: 0x%04X, 道路号: %d, 距离: %d, 速度: %d, 加速度: %d\n",
                   get_current_time_string(time_buf, sizeof(time_buf)),
                   (obj->dev_type == RADAR_INCOMING) ? ">>>>>>>>>来向" : "<<<<<<<<<去向",
                   obj->id, obj->report_lane, obj->dist_y, speed_y, obj->acceleration);
            report_acceleration(obj);
        }
    }
}

static void report_obstacle_start(uint8_t lane_id, int16_t start_pos, int8_t dev_type)
{
    radar_packet_84_t packet_84 = {0};
    packet_84.header.event_type = 0xd;  // 障碍物事件
    packet_84.body.va.obj_id = 0;
    packet_84.body.va.obj_lane = lane_id;
    packet_84.body.va.obj_type = 0;
    packet_84.body.va.obj_length = 0;
    packet_84.body.va.obj_dist_y_low = start_pos;
    packet_84.body.va.obj_dist_x_low = 0;
    packet_84.body.va.obj_speed = 0;

    uint8_t time_stamp[8] = {0};
    get_time_bytes(time_stamp, 8);
    send_event_to_platform(&packet_84, time_stamp, dev_type);
}

int get_obj_lane(radar_obj_info_t *radar_info, uint8_t dev_type)
{
    Queue_t *queue = (dev_type == RADAR_INCOMING) ? g_event_manager.incoming_obj_static_queue : g_event_manager.outgoing_obj_static_queue;
    int count = get_queue_count(queue);
    int8_t lane = radar_info->lane;
    for (int i = 0; i < count; i++) {
        obj_static_t *item = queue_get_node(queue, from_tail, i);
        if (item && item->id == radar_info->id) {
            lane = item->report_lane;
            break;
        }
    }
    return lane;
}

void update_obj_statistics(radar_obj_info_t *radar_info, int8_t dev_type)
{
    obj_static_t *obj = NULL;
    Queue_t *queue = (dev_type == RADAR_INCOMING) ? g_event_manager.incoming_obj_static_queue : g_event_manager.outgoing_obj_static_queue;
    int count = get_queue_count(queue);
    int64_t current_time = get_current_time_in_milliseconds();
    int row = -1, col = -1;

    // 在队列中查找是否已经存在该 id 的对象
    for (int i = 0; i < count; i++) {
        obj_static_t *item = queue_get_node(queue, from_tail, i);
        if (item && item->id == radar_info->id) {
            obj = item;
            break;
        }
    }

    // 如果找到了，则按照要求进行比较和更新
    if (obj != NULL) {
        obj->dist_x = radar_info->dist_x;
        obj->dist_y = radar_info->dist_y;
        obj->current_speed = radar_info->speed_y;
        update_lane(obj, radar_info->lane);
        update_acceleration(obj, radar_info->speed_y);
    }

    else {
        // 如果没有找到，则创建一个新的对象并添加到队列中
        obj_static_t new_obj = {0};
        new_obj.id = radar_info->id;
        new_obj.dev_type = dev_type;
        new_obj.report_lane = radar_info->lane;
        new_obj.current_lane = radar_info->lane;
        new_obj.change_time = current_time;
        new_obj.dist_x = radar_info->dist_x;
        new_obj.dist_y = radar_info->dist_y;
        new_obj.last_speed_time = current_time;
        new_obj.last_speed = radar_info->speed_y;
        new_obj.current_speed = radar_info->speed_y;
        new_obj.acceleration = 0;
        queue_enqueue(queue, &new_obj);
    }

    row = radar_info->lane;
    col = radar_info->dist_y / 100;
    if (col >= 100) {
        col = 99;
    }
    else if (col < 0) {
        col = 0;
    }
    // 更新最后一次被看到的时间
    if (dev_type == RADAR_INCOMING) {
        g_event_manager.incoming_last_seen_time[row][col] = time(NULL);
        g_event_manager.incoming_report[row][col] = false;
        // printf("来向雷达 道路号: %d, id: 0x%04X, 距离: %d, 对应距离: %d\n",
        //        radar_info->lane, radar_info->id, radar_info->dist_y, col * 100);
    }
    else if (dev_type == RADAR_OUTGOING) {
        g_event_manager.outgoing_last_seen_time[row][col] = time(NULL);
        g_event_manager.outgoing_report[row][col] = false;
        // printf("去向雷达 道路号: %d, id: 0x%04X, 距离: %d, 对应距离: %d\n",
        //        radar_info->lane, radar_info->id, radar_info->dist_y, col * 100);
    }
}

void send_event_snapshot(char *file_path, int64_t time_stamp, int8_t dev_type, int8_t event_id)
{
    char *base64_encoded = NULL;
    base64_encoded = file_to_base64(file_path);
    if (base64_encoded == NULL) {
        fprintf(stderr, "Failed to encode file to base64\n");
        return;
    }

    CURLcode res;
    struct curl_slist *headers = NULL;

    /* 1) 设置请求 URL */
    curl_easy_setopt(curl, CURLOPT_URL, g_config.upload_image_url);
    headers = curl_slist_append(headers, "Content-Type: application/json");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

    /* 2) 设置请求方法为 POST */
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");

    /* 3) 设置请求体 */
    char dev_num[10] = {0};
    char dev_num_str[32] = {0};
    get_device_id(dev_num, dev_type);
    hex_to_str(dev_num, 10, dev_num_str, 32);
    cJSON *json = cJSON_CreateObject();
    cJSON_AddNumberToObject(json, "timestamp", time_stamp);
    cJSON_AddStringToObject(json, "base64", base64_encoded);
    cJSON_AddStringToObject(json, "deviceNum", dev_num_str);
    cJSON_AddNumberToObject(json, "eventType", event_id);
    cJSON_AddNumberToObject(json, "imgType", 0x01);
    char *json_str = cJSON_Print(json);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_str);

    res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform() failed: %s\n",
                curl_easy_strerror(res));
    }
    else {
        /* 请求成功，打印 HTTP 状态码和响应体 */
        long http_code = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        printf("HTTP status: %ld\n", http_code);
        printf("Response body:\n%s\n", response);
    }

    /* 4) 清理 JSON 对象 */
    cJSON_Delete(json);
    free(json_str);
    free(base64_encoded);
    free(response);
    response = NULL;

    /* 清理 */
    curl_slist_free_all(headers);
}

void init_curl_config()
{
    response = malloc(1);
    response[0] = '\0';

    curl = curl_easy_init();
    if (!curl) {
        fprintf(stderr, "Failed to initialize CURL\n");
        free(response);
        return NULL;
    }
    /* 设置请求 URL */
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
}

void destroy_curl_config()
{
    if (curl) {
        curl_easy_cleanup(curl);
        curl = NULL;
    }
    if (response) {
        free(response);
        response = NULL;
    }
}

char *get_video_ip_from_distance(int distance, int8_t dev_type)
{
    if (dev_type == RADAR_INCOMING) {
        if (distance < 1400) {
            return g_config.incoming_near_focus_video_ip;
        }
        else {
            return g_config.incoming_far_focus_video_ip;
        }
    }
    else if (dev_type == RADAR_OUTGOING) {
        if (distance < 1400) {
            return g_config.outgoing_near_focus_video_ip;
        }
        else {
            return g_config.outgoing_far_focus_video_ip;
        }
    }
    return NULL;
}

void report_obstacle_event(int lane, int distance, int8_t dev_type)
{
    char ip_str[16] = {0};
    user_camera_login_info camera_info = {0};
    ip_bytes_to_str(get_video_ip_from_distance(distance, dev_type), camera_info.cameraip);
    strcpy(camera_info.usrname, USERNAME);
    strcpy(camera_info.password, PASSWORD);
    capture_snapshot("snapshot.jpg", &camera_info);

    // 发送快照到平台
    int64_t time_stamp = get_current_time_in_milliseconds();
    report_obstacle_start(lane, distance, dev_type);
    send_event_snapshot("snapshot.jpg", time_stamp, dev_type, 0x0C);
}

#define TIMEOUT_SEC (150)

/**
 * @brief 检查障碍物格子是否满足上报条件，若满足则触发上报。
 *
 * 逻辑说明：
 * - 判断某个 cell（栅格）是否长时间未被目标覆盖（last_seen 超时）
 * - 如果未覆盖时间超过阈值且该位置附近发生大量变道，则认定为障碍物
 * - 上报第一个格子，并将后续连续的超时格子也标记为已上报，防止重复触发
 *
 * @param dev_type 来向或去向（RADAR_INCOMING / RADAR_OUTGOING）
 * @param current_time_ms 当前系统时间（单位：毫秒）
 */
void check_obstacle(int8_t dev_type, int current_time_ms)
{
    event_manager_t *m = &g_event_manager;

    // 获取方向相关的状态记录数组
    int(*last_seen)[OBSTACLE_SEGMENT] =
        (dev_type == RADAR_INCOMING) ? m->incoming_last_seen_time : m->outgoing_last_seen_time;
    bool(*reported)[OBSTACLE_SEGMENT] =
        (dev_type == RADAR_INCOMING) ? m->incoming_report : m->outgoing_report;
    int *seen_range =
        (dev_type == RADAR_INCOMING) ? m->incoming_seen_range : m->outgoing_seen_range;

    // 当前车道检测的列（Y轴）范围
    int start = seen_range[0], end = seen_range[1];

    // 检测方向：来向从尾往前扫，去向从前往尾扫
    int dir = (dev_type == RADAR_INCOMING) ? -1 : 1;

    // 遍历每一条车道
    for (int row = 0; row < g_config.lane_num - 1; ++row) {
        bool in_block = false;                // 当前是否进入了一个“连续超时段”
        bool should_mark_rest_block = false;  // 是否需要将后续格子也标记为“已上报”

        // 设置起始扫描位置（根据方向）
        int cell = (dir > 0) ? start : end;

        // 逐格扫描，从 start 到 end，按 dir 方向前进
        for (; cell >= start && cell <= end; cell += dir) {
            int last = last_seen[row][cell];
            if (last == 0) {
                // 该格子从未被观测过，跳过
                continue;
            }

            // 如果当前时间距离上次被观测的时间太短，说明格子仍然活跃，跳过
            if (last == 0 || (current_time_ms - last < TIMEOUT_SEC)) {
                // 离开了可能的障碍物段，清除状态
                in_block = false;
                should_mark_rest_block = false;
                continue;
            }

            // 当前格子为“超时格子”（长时间无人通过）
            if (!in_block) {
                // 第一次进入连续超时块
                in_block = true;

                if (!reported[row][cell]) {
                    int distance = cell * 100;  // 将列号转为物理距离（假设每格100cm）
                    int lc_count = get_recent_lane_change_count_by_distance(distance, dev_type);

                    // 判断在该区域是否发生过频繁变道
                    if (lc_count >= LC_THRESHOLD) {
                        // 满足条件，障碍物成立，上报
                        printf("检查到 %s方向的障碍物, row: %d, cel: %d, 变道车辆数量: %d\n",
                               (dev_type == RADAR_INCOMING) ? "来向" : "去向",
                               row, cell, lc_count);
                        // undo 通过拍照来判断障碍物是什么
                        //  进行上报
                        report_obstacle_event(row, distance, dev_type);

                        // 标记该格子已上报，防止重复上报
                        reported[row][cell] = true;

                        // 后续连续格子也标记为上报（同一障碍物块）
                        should_mark_rest_block = true;
                    }
                }
            }
            else if (should_mark_rest_block && !reported[row][cell]) {
                // 后续连续的超时格子（属于同一个障碍物区域），也标记为已上报
                reported[row][cell] = true;
            }
        }
    }
}

void report_chain_collision_event(sstk_obj_t *obj)
{
    if (update_event_queue_sstk(obj, 0xB) == false) {
        return;  // 事件已经存在，直接返回
    }
    radar_packet_84_t packet_84 = {0};
    packet_84.header.event_type = 0xb;               // 碰撞事件
    packet_84.body.va.obj_id = 0;                    // 碰撞链事件没有具体目标 ID
    packet_84.body.va.obj_lane = obj->lane_id;       // 碰撞事件车道 ID
    packet_84.body.va.obj_type = 0;                  // 碰撞事件没有具体目标类型
    packet_84.body.va.obj_length = 0;                // 碰撞事件没有具体目标长度
    packet_84.body.va.obj_dist_y_low = obj->dist_y;  // 碰撞事件起始 Y 轴位置
    packet_84.body.va.obj_dist_x_low = obj->dist_x;  // 碰撞事件起始 X 轴位置

    uint8_t time_stamp[8] = {0};
    get_time_bytes(time_stamp, 8);
    send_event_to_platform(&packet_84, time_stamp, RADAR_INCOMING);  // 假设是来向雷达上报
}

/* 拥堵事件上报：车道 ID、起始时间、连续车辆数 */
void report_congestion_event(sstk_obj_t *start, sstk_obj_t *stop, int16_t congestion_length)
{
    if (update_event_queue_sstk(start, 0x43) == false) {
        return;  // 事件已经存在，直接返回
    }
    else if (update_event_queue_sstk(stop, 0x43) == false) {
        return;  // 事件已经存在，直接返回
    }

    int congestion_level = 0;
    radar_packet_84_t packet_84 = {0};
    packet_84.header.event_type = 0x43;

    packet_84.body.tj2.lane_num = start->lane_id;
    packet_84.body.tj2.traffic_jam_length = congestion_length;  // 拥堵长度

    // 根据拥堵长度设置拥堵等级
    if (congestion_length < 400) {
        congestion_level = 1;  // 轻度拥堵
    }
    else if (congestion_length < 1000) {
        congestion_level = 2;  // 中度拥堵
    }
    else {
        congestion_level = 3;                                // 重度拥堵
    }
    packet_84.body.tj2.congestion_level = congestion_level;  // 拥堵等级
    packet_84.body.tj2.is_overflow = 0;
    packet_84.body.tj2.start_x = start->dist_x;              // 起始 X 轴位置
    packet_84.body.tj2.start_y = start->dist_y;              // 起始 Y 轴位置

    uint8_t time_stamp[8] = {0};
    send_event_to_platform(&packet_84, time_stamp, RADAR_INCOMING);
}

/* 停车事件上报：车道 ID、起始时间、连续车辆数 */
void report_parking_event(sstk_obj_t *obj)
{
    if (update_event_queue_sstk(obj, 0x0d) == false) {
        return;  // 事件已经存在，直接返回
    }

    radar_packet_84_t packet_84 = {0};
    packet_84.header.event_type = 0x0d;
    packet_84.body.va.obj_id = obj->id;
    packet_84.body.va.obj_lane = obj->lane_id;
    packet_84.body.va.obj_type = obj->type;
    packet_84.body.va.obj_length = obj->length;
    packet_84.body.va.obj_dist_y_low = obj->dist_y;
    packet_84.body.va.obj_dist_x_low = obj->dist_x;
    packet_84.body.va.obj_speed = obj->speed_y;
    uint8_t time_stamp[8] = {0};
    send_event_to_platform(&packet_84, time_stamp, RADAR_INCOMING);
}

void report_construction_event()
{
}

/**
 * @brief 碰撞链检测逻辑。
 *
 * 该函数用于从事件队列中查找是否存在两个停车（或几乎停车）目标在时间和空间上接近，
 * 若满足条件，则认为发生了“链式碰撞”并立即上报，执行一次后立即返回。
 */
static void detect_collision_events(void)
{
    // 获取事件队列中的目标数，若不足两个则无需检测
    int count = get_queue_count(g_event_manager.sstk_event_queue);
    if (count < 2)
        return;

    /**
     * 只判断第一对符合条件的目标，判定标准：
     * - 两个目标都属于停车（event == 0x01 或 duration 超过阈值）
     * - 时间差小于一定阈值（如 3 秒）
     * - Y 方向距离小于阈值（如 1.5 米）
     */

    for (int i = 0; i < count; i++) {
        // 获取第 i 个事件
        sstk_event_static_t *a = queue_get_node(g_event_manager.sstk_event_queue, from_tail, i);
        if (!a)
            continue;

        // 判断目标 a 是否为“停车目标”
        bool a_stop = (a->event == 0x01);                           // 事件类型为停车
        a_stop |= (a->duration > COLLISION_DURATION_THRESHOLD_MS);  // 停车持续时间长

        if (!a_stop)
            continue;  // 如果 a 不是停车状态，则跳过

        // 遍历后续目标，查找与 a 匹配的目标 b
        for (int j = i + 1; j < count; j++) {
            sstk_event_static_t *b = queue_get_node(g_event_manager.sstk_event_queue, from_tail, j);
            if (!b)
                continue;

            // 判断目标 b 是否也为停车状态
            bool b_stop = (b->event == 0x01);
            b_stop |= (b->duration > COLLISION_DURATION_THRESHOLD_MS);
            if (!b_stop)
                continue;

            // 如果是同一个目标 ID，跳过（不能和自己比较）
            if (b->obj_info.id == a->obj_info.id)
                continue;

            // ---------- 时间判断 ----------
            // 计算首次上报时间差
            int64_t dt = b->first_report_time - a->first_report_time;
            if (dt < 0)
                dt = -dt;
            if (dt > COLLISION_TIME_THRESHOLD_MS)
                continue;  // 时间差过大，跳过

            // ---------- 空间判断 ----------
            // Y 轴方向上的距离差
            int16_t dy = abs(b->obj_info.dist_y - a->obj_info.dist_y);
            if (dy > COLLISION_DISTY_THRESHOLD)
                continue;  // 距离差过大，跳过

            // ---------- 满足所有条件 ----------
            // 上报链式碰撞事件，并立即退出函数（只上报第一对）
            report_chain_collision_event(&a->obj_info);
            return;
        }
    }
}

/* —— 拥堵检测 + 计算拥堵长度 —— */
// 满足贵州测试要求(多辆车慢行，基于森斯泰克缓行事件来处理)
static void detect_congestion_events(void)
{
    // 获取事件队列中事件数量
    int count = get_queue_count(g_event_manager.sstk_event_queue);
    if (count < CONGESTION_COUNT_THRESHOLD)
        return;  // 数量不够，无法形成拥堵链，直接返回

    // 分配内存，用于记录已参与拥堵链的 obj_id，防止重复使用
    uint16_t *used_ids = malloc(count * sizeof(uint16_t));
    if (!used_ids)
        return;        // 分配失败则直接返回
    int used_cnt = 0;  // 已处理目标数量

    // 遍历每个事件作为“起始点”尝试构建拥堵链
    for (int i = 0; i < count; i++) {
        sstk_event_static_t *start =
            queue_get_node(g_event_manager.sstk_event_queue, from_tail, i);
        if (!start)
            continue;  // 空节点跳过

        // 检查当前目标是否已被处理，或不是缓行事件（0xA）
        bool already = false;
        for (int u = 0; u < used_cnt; u++) {
            if (used_ids[u] == start->obj_info.id) {
                already = true;
                break;
            }
        }
        if (already || start->event != 0xA)
            continue;

        // 初始化链条统计信息
        used_ids[used_cnt++] = start->obj_info.id;  // 标记该目标已处理
        uint8_t lane = start->obj_info.lane_id;     // 当前车道
        int run_len = 1;                            // 拥堵链长度初始为1
        int64_t t0 = start->first_report_time;      // 记录起始时间
        int16_t min_y = start->obj_info.dist_y;     // 最小Y（最前车）
        int16_t max_y = start->obj_info.dist_y;     // 最大Y（最后车）
        sstk_event_static_t *min_evt = start;       // 保存最前方目标指针
        sstk_event_static_t *max_evt = start;       // 保存最后方目标指针

        // 向后查找满足条件的其他目标加入链条
        for (int j = i + 1; j < count; j++) {
            sstk_event_static_t *c =
                queue_get_node(g_event_manager.sstk_event_queue, from_tail, j);
            if (!c)
                continue;

            // 检查是否已处理，或与起始目标重复
            bool used = false;
            for (int u = 0; u < used_cnt; u++) {
                if (used_ids[u] == c->obj_info.id) {
                    used = true;
                    break;
                }
            }
            if (used || c->obj_info.id == start->obj_info.id)
                continue;

            // 要求同车道 + 缓行事件（event == 0xA）
            if (c->obj_info.lane_id != lane || c->event != 0xA)
                continue;

            // 时间窗口判断，必须在 CONGESTION_TIME_WINDOW_MS 内
            int64_t dt = c->first_report_time - t0;
            if (dt < 0)
                dt = -dt;
            if (dt > CONGESTION_TIME_WINDOW_MS)
                continue;

            // 满足条件，加入链条
            used_ids[used_cnt++] = c->obj_info.id;
            run_len++;

            // 更新最前目标（Y 最小）和最后目标（Y 最大）
            if (c->obj_info.dist_y < min_y) {
                min_y = c->obj_info.dist_y;
                min_evt = c;
            }
            if (c->obj_info.dist_y > max_y) {
                max_y = c->obj_info.dist_y;
                max_evt = c;
            }
        }

        // 如果链条长度达到阈值，计算物理长度并上报事件
        if (run_len >= CONGESTION_COUNT_THRESHOLD) {
            int16_t length = max_y - min_y;  // 拥堵长度 = 尾车 - 头车 Y 值差
            report_congestion_event(&min_evt->obj_info, &max_evt->obj_info, length);
        }
    }

    // 释放用于去重的资源
    free(used_ids);
}

/**
 * @brief 停车事件检测。
 *
 * 遍历事件队列，找出所有满足以下条件的目标并上报停车事件：
 * - 事件类型为 PARKING_EVENT_CODE（停车）
 * - 停车持续时间超过设定阈值
 */
static void detect_parking_events()
{
    // 获取当前事件队列中的事件总数
    int count = get_queue_count(g_event_manager.sstk_event_queue);
    if (count < 1)
        return;  // 队列为空，无需处理

    // 遍历队列中的所有事件
    for (int i = 0; i < count; i++) {
        // 获取第 i 个事件（从队尾向前查）
        sstk_event_static_t *a = queue_get_node(g_event_manager.sstk_event_queue, from_tail, i);
        if (!a)
            continue;  // 无效节点则跳过

        // 判断该事件是否为停车事件，且持续时间超过设定阈值
        if (a->event == PARKING_EVENT_CODE && a->duration > PARKING_TIME_THRESHOLD_MS) {
            // 满足条件，则上报停车事件（如记录或通知平台）
            report_parking_event(&a->obj_info);
        }
    }
}

// 和停车事件相同，行人事件也需要持续超过 1 分钟
#define TIME_THRESHOLD_MS (60 * 1000)

// 距离阈值：30 米 → 30*30 用于比较平方距离
#define DISTANCE_THRESHOLD_M  30
#define DISTANCE_THRESHOLD_SQ (DISTANCE_THRESHOLD_M * DISTANCE_THRESHOLD_M)

/**
 * @brief 检测“施工事件”：定义为“同一时空中出现一个长时间停车目标 + 一个长时间出现的行人”。
 *
 * 逻辑：
 * - 从事件队列中找出持续时间长的停车事件
 * - 与之配对判断是否存在时间重叠的行人事件
 * - 且两者物理位置接近（距离平方小于阈值）
 * 满足条件则上报施工事件。
 */
// 满足贵州测试要求(施工事件，基于森斯泰克行人事件来处理)
// 可以尝试通过拍照叫ai视频识别来判断是否有施工车辆
static void detect_construction_event(void)
{
    int count = get_queue_count(g_event_manager.sstk_event_queue);
    if (count < 2)
        return;  // 不足两个事件，不可能构成组合事件，直接返回

    // 遍历所有事件，寻找“停车事件”
    for (int i = 0; i < count; i++) {
        sstk_event_static_t *park = queue_get_node(g_event_manager.sstk_event_queue, from_tail, i);
        if (!park)
            continue;

        // 判断是否为停车事件，且停车持续时间超过阈值
        if (park->event != PARKING_EVENT_CODE || park->duration <= TIME_THRESHOLD_MS)
            continue;

        // 再次遍历所有事件，寻找“行人事件”
        for (int j = 0; j < count; j++) {
            if (j == i)
                continue;  // 忽略自己和自己的配对

            sstk_event_static_t *ped = queue_get_node(g_event_manager.sstk_event_queue, from_tail, j);
            if (!ped)
                continue;

            // 判断是否为行人事件，且持续时间也超过阈值
            if (ped->event != PEDESTRIAN_EVENT_CODE || ped->duration <= TIME_THRESHOLD_MS)
                continue;

            // ---------- (1) 时间重叠判断 ----------
            uint64_t start_p = park->first_report_time;
            uint64_t end_p = start_p + park->duration;
            uint64_t start_q = ped->first_report_time;
            uint64_t end_q = start_q + ped->duration;

            // 判断两个事件的时间是否重叠
            // 条件：(start_p < end_q) && (start_q < end_p)
            if (!(start_p < end_q && start_q < end_p))
                continue;

            // ---------- (2) 空间接近判断 ----------
            int32_t dx = park->obj_info.dist_x - ped->obj_info.dist_x;
            int32_t dy = park->obj_info.dist_y - ped->obj_info.dist_y;

            // 欧氏距离平方是否小于设定阈值
            if ((dx * dx + dy * dy) > DISTANCE_THRESHOLD_SQ)
                continue;

            // ---------- 同时满足两个条件，判定为施工事件 ----------
            // 此处可做事件上报、记录、调度等操作
            report_construction_event();
            return;  // 一旦检测到一个施工事件，即可返回，不重复上报
        }
    }
}

void check_event()
{
    if (g_config.radar_type == 1) {
        // check_obstacle(RADAR_INCOMING, time(NULL));
        // check_obstacle(RADAR_OUTGOING, time(NULL));
    }
    else if (g_config.radar_type == 2) {
        detect_collision_events();
        detect_congestion_events();
        // detect_parking_events();  // 去掉
        detect_construction_event();
    }
}

void init_event()
{
    g_event_manager.incoming_seen_range[0] = g_config.incoming_obstacle_range[0] / 100;
    g_event_manager.incoming_seen_range[1] = g_config.incoming_obstacle_range[1] / 100;
    g_event_manager.outgoing_seen_range[0] = g_config.outgoing_obstacle_range[0] / 100;
    g_event_manager.outgoing_seen_range[1] = g_config.outgoing_obstacle_range[1] / 100;

    dhsdk_init();
}

void *event_thread(void *arg)
{
    // init_curl_config();
    init_event();

    while (1) {
        check_event();
        sleep(1);  // 1s
    }

    // 释放资源
    // destroy_curl_config();
    return NULL;
}

void init_event_queue()
{
    if (g_config.radar_type == 1) {
        INIT_QUEUE(g_event_manager.incoming_obj_static_queue, OBJ_STATIC_QUEUE_SIZE, sizeof(obj_static_t), NULL);
        INIT_QUEUE(g_event_manager.outgoing_obj_static_queue, OBJ_STATIC_QUEUE_SIZE, sizeof(obj_static_t), NULL);
        for (int i = 0; i < SEGMENT_COUNT; i++) {
            INIT_QUEUE(g_event_manager.incoming_change_lane_static_queue[i], WINDOW_SLOTS, sizeof(uint16_t), NULL);
            INIT_QUEUE(g_event_manager.outgoing_change_lane_static_queue[i], WINDOW_SLOTS, sizeof(uint16_t), NULL);
        }
    }
    else if (g_config.radar_type == 2) {
        INIT_QUEUE(g_event_manager.sstk_event_queue, SSTK_EVENT_STATIC_QUEUE_SIZE, sizeof(sstk_event_static_t), NULL);
    }
}

void destroy_event_queue()
{
    if (g_config.radar_type == 1) {
        SAFE_DESTROY_QUEUE(g_event_manager.incoming_obj_static_queue);
        SAFE_DESTROY_QUEUE(g_event_manager.outgoing_obj_static_queue);
        for (int i = 0; i < SEGMENT_COUNT; i++) {
            SAFE_DESTROY_QUEUE(g_event_manager.incoming_change_lane_static_queue[i]);
            SAFE_DESTROY_QUEUE(g_event_manager.outgoing_change_lane_static_queue[i]);
        }
    }
    else if (g_config.radar_type == 2) {
        SAFE_DESTROY_QUEUE(g_event_manager.sstk_event_queue);
    }
}

pthread_t start_event_server(void)
{
    pthread_t event_thread_id;
    init_event_queue();
    // 创建一个线程来运行客户端
    if (pthread_create(&event_thread_id, NULL, event_thread, NULL) != 0) {
        perror("Thread creation failed");
        exit(1);
    }
    pthread_detach(event_thread_id);  // 分离线程，避免资源泄漏
    return event_thread_id;
}

void stop_event_server(void)
{
    destroy_event_queue();
}